import numpy as np
from jili.core.printlog import print
from jili.core import load,save
import pandas as pd
import pyfinance as pf
import matplotlib.pyplot as plt
import datetime
from copy import deepcopy
from jili.pos.evaluate_ss import performance_net
from jili.data.db import getdb_client
import os
from jili.xtlib.predata import xtpredata
# from jili.core import get_models
# task_model=get_models("research.pos",included__init__=False)

class pos_frame:
    def __init__(self,priceurl=r"F:",cash=0,isdetail=False,isset_benck=True):
        #最新资产类
        self.priceurl=priceurl
        self.fund=self.create_fund(cash)
        self.pos = {}  #当前持仓   obj:{bs:v}
        self.orders_book = {}  # 当日委托
        self.orders_working_book = {}  # 可撤单
        #重要关键数据
        self.curr_posrate = 0
        self.posrate_limit=1
        self.isclosetime = False  # 是否平仓时间
        self.timekey=None
        self.isdetail=isdetail
        self.datatool_index={}

        self.other = {}  # 其它数据
        self.otherdata_graph = {}  # 其它画图数据
        self.otherpos_pldata={}
        self.price_pool = {}  # 最新行情
        self.bar_pool={} #最新K线
        self.bar_k1d={}
        self.close_monitor=[]#平仓小策略
        self.presettle_byday={}
        self.predata={}
        self.fee=0

        self.r={}
        #绩效参数
        if cash==0:
            self.cash0 =1
        else:
            self.cash0 = cash  # 初始资金
        self.cashin_total=0
        self.havecashin=False
        self.cashin_book={}
        self.holdcash=0
        self.maxfund = cash  # 资产最高位
        self.curr_return = 0  # 当前收益率
        self.is_graphs = False
        # self.benckmark_objs = {"国证2000": {"obj": "399303.SZ", "is_selected": True, "aixs": 1},
        #                        "沪深300": {"obj": "000300.SH", "is_selected": False, "aixs": 1},
        #                        "中证500": {"obj": "000905.SH", "is_selected": False, "aixs": 1},
        #                        "创业板": {"obj": "399006.SZ", "is_selected": False, "aixs": 1}}
        # self.set_benck_mark(self.benckmark_objs)
        self.benckmark_objs = {"国证2000": {"obj": "399303", "is_selected": True, "aixs": 1},
                               "沪深300": {"obj": "000300", "is_selected": False, "aixs": 1},
                               "中证500": {"obj": "000905", "is_selected": False, "aixs": 1},
                               "创业板": {"obj": "399006", "is_selected": False, "aixs": 1}}
        self.benck_mark = {}
        if isset_benck:
            self.set_benck_mark(self.benckmark_objs)
        self.return_byday=0
        #历史资产类
        self.orders_his = []  #所有开平订单
        self.pos_his={}  #历史持仓表
        self.posrate_his = {}  # 每日仓位
        self.return_his = {}  # 每日收益率
        self.fund_his = {}  # 历史资金表 date,float
        #按回测bar类  一般不用  高频才用
        self.posrates_bybar = {}  #按bar仓位
        self.fund_bybar = {} #按bar资金
        self.close_bybar = {} #按bar收盘价
        #交易指令
        self.auto_order = {}  # 自动单
        self.submit_order_deal = {"buy":self.buy,"sell":self.sell,
                                  "reverse_order":self.reverse_order,
                                    "openbuy": self.openbuy,
                                  "opensell": self.opensell,
                                  "closebuy": self.closebuy,
                                  "closesell": self.closesell}
    #----------------------------------交易下单类开始------------------------------------------------
    def add_benckmark(self,name,obj,is_selected=True):
        self.benckmark_objs[name]={"obj":obj, "is_selected": is_selected, "aixs": 1}
        self.set_benck_mark(self.benckmark_objs)
    def submit_order(self, action, **order):
        # if action in self.submit_order_deal.keys():
        #     print(1)
        # else:
        #     print(2,action,type(action))
        f=self.submit_order_deal[action]
        return f(**order)
    def buy(self,**order):
        #(self, timekey, obj, price,qty=None,posrate=1,amount=None,msg="",is_commission=False):
        """:cvar
        return istrue,orderid
        """
        self.closebuy(**order)
        r=self.openbuy(**order)
        # print("pos_frame没有定义:buy")
        return r
    def resetposrate(self, posrate, date, tradebars):
        """:cvar
                        return istrue,orderid
                        """
        print("pos_frame没有定义:resetposrate")
        return 1
    def sell(self, **order):
        """:cvar
                return istrue,orderid
                """
        self.closesell(**order)
        return self.opensell(**order)
    def closesell(self, **order):
        """:cvar
                return istrue,orderid
                """
        print("pos_frame没有定义:closesell")
        return False,""
    def closebuy(self, **order):
        """:cvar
                return istrue,orderid
                """
        print("pos_frame没有定义:closebuy")
        return False,""
    def opensell(self,**order):
        """:cvar
                return istrue,orderid
                """
        print("pos_frame没有定义:opensell")
        return False,""
    def openbuy(self, **order):
        """:cvar
                return istrue,orderid
                """
        print("pos_frame没有定义:openbuy")
        return False,""
    def reverse_order(self, **order):
        """:cvar
                return istrue,orderid
                """
        print("pos_frame没有定义:reverse_order")
        return False,""


    def clearpos(self, date, data={},msg=""):
        """:cvar
        data:{obj:bar/tick}
        必须支持以上业务解析：支持多品种的回测与结算；单品种是多品种的一个特例

        return istrue,orderid
        """
        print("pos_frame没有定义:clearpos")
        return False,""

    # ----------------------------------交易下单类结束------------------------------------------------
    # ----------------------------------资产计算类开始------------------------------------------------
    #前两个研究用
    def cash2pos(self,amount,fee=0):
        self.fund["cash"]=self.fund["cash"]-amount
        self.fund["fee"]=self.fund["fee"]+fee
        return self.fund["cash"]
    def pos2cash(self,amount,fee=0):
        self.fund["cash"] = self.fund["cash"] + amount
        self.fund["fee"] = self.fund["fee"] + fee
        return self.fund["cash"]
    def get_cashin_byday(self,d):
        date = datetime.datetime(d.year, d.month, d.day)
        if date in self.cashin_book.keys():
            return self.cashin_book[date]
        else:
            return 0
    def cashin(self,d,amount):
        if amount>0:
            self.fund["cash"] = self.fund["cash"] + amount
            self.fund["cashin"]=self.fund["cashin"]+amount
            # self.fund["balance"] = self.fund["balance"] + amount
            self.cashin_total=self.cashin_total+amount
            self.havecashin=True
            self.holdcash=0
            date = datetime.datetime(d.year, d.month, d.day)
            self.cashin_book[date] = amount
            print("成功入金",self.fund["cash"],amount)
            return True
        else:
            print("入金不能为负", self.fund["cash"],amount)
            return False
    def cashout(self,d,amount):
        if amount>0:
            if self.fund["cash"]>=amount:
                self.fund["cash"] = self.fund["cash"] - amount
                self.fund["cashin"] = self.fund["cashin"] - amount
                # self.fund["balance"]=self.fund["balance"]-amount
                self.cashin_total=self.cashin_total-amount
                self.havecashin = True
                self.holdcash=0
                date=datetime.datetime(d.year,d.month,d.day)
                self.cashin_book[date]=amount
                print("成功出金",self.fund["cash"], amount)
                return True
            else:
                print("可取资金不足",  self.fund["cash"], amount)
                return False
        else:
            print("出金不能为负", self.fund["cash"],amount)
            return False
    def reset_maxfund(self):
        self.maxfund=0
    def calc_posrate(self):
        print("pos_frame没有定义:calc_posrate")
        return None
    def calc_avlfund(self):
        print("pos_frame没有定义:calc_avlfund")
        return None
    def calc_fund(self):
        print("pos_frame没有定义:calc_fund")
        return None
    def calc_pl0(self):
        print("pos_frame没有定义:calc_pl0")
        return None
    def calc_pl(self):
        print("pos_frame没有定义:calc_pl")
        return None
    def calc_balance(self):
        print("pos_frame没有定义:calc_balance")
        return None
    def calc_close_avlqty(self,obj,bs):
        print("pos_frame没有定义:calc_close_avlqty")
        return None
    def calc_open_avlqty(self,obj,bs,limitcash_this=None,limitcash=None):
        print("pos_frame没有定义:calc_open_avlqty")
        return None
    def calc_working_qty(self,obj,bs):
        print("pos_frame没有定义:calc_working_qty")
        return None
    def calc_working_orders(self):
        print("pos_frame没有定义:calc_working_orders")
        return None
    def havelongpos(self, obj):
        rst = False
        if obj in self.pos.keys():
            if "buy" in self.pos[obj].keys():
                if self.pos[obj]["buy"]["qty"] > 0:
                    rst = True
        return rst
    def haveshortpos(self, obj):
        rst = False
        if obj in self.pos.keys():
            if "sell" in self.pos[obj].keys():
                if self.pos[obj]["sell"]["qty"] > 0:
                    rst = True
        return rst
    def getposnum(self):
        rst = 0
        for obj, p in self.pos.items():
            for bs, v in p.items():
                if v["qty"] != 0:
                    rst = rst + 1
        return rst
    def getposordersnum(self):
        rst = 0
        for obj, p in self.pos.items():
            for bs, v in p.items():
                if v["qty"] != 0:
                    rst = rst + len(v["detail"])
        return rst
    def getorders(self):
        od = pd.DataFrame(self.orders_his)
        od["r"] = 100 * (od["sellprice"] - od["buyprice"]) / od["buyprice"]
        od["holddays"] = od["closetimekey"] - od["opentimekey"]
        od["holddays"] = od["holddays"].apply(lambda x: x.days)
        return od
    def onpos(self,msg):
        self.pos.update(msg)
    def onfund(self,msg):
        self.fund.update(msg)
    def onorder(self,msg):
        print("pos_frame没有定义:onorder")
        return None
    def get_prebalance_byday(self,timekey):
        d=datetime.datetime(timekey.year,timekey.month,timekey.day)
        l=list(self.fund_his.keys())
        l.sort()
        fund=self.cash0
        for i in reversed(l):
            if d>i:
                fund=self.fund_his[i]
                break
        return fund
    def check_calcpl(self,pl,close_amount):
        if self.orders_his:
            ordersd = pd.DataFrame(self.orders_his)
            fund= self.cash0+ ordersd["pl"].sum()+pl+self.cashin_total
        else:
            fund = self.cash0 +  pl+self.cashin_total
        fund0=self.fund["cash"]+close_amount
        if int(fund)!=int(fund0):
            print("check_calcpl_err 结算错误",pl,close_amount,fund,fund0,self.fund["cash"],self.cash0,self.cashin_total)
        else:
            print("check_calcpl", pl, close_amount, fund, fund0,self.fund["cash"],self.cash0,self.cashin_total)

    # ----------------------------------资产计算类结束------------------------------------------------
    # ----------------------------------行情等其他数据类开始------------------------------------------------
    def save_presettle_byday(self,obj,d,settle_price):
        if obj not in self.presettle_byday.keys():
            self.presettle_byday[obj] = {}
        self.presettle_byday[obj][d] = settle_price
    def get_lastprice(self,obj):
        if obj in self.price_pool.keys():
            t=self.price_pool[obj]
            return t["LastPrice"]
        elif obj in self.bar_pool.keys():
            t = self.bar_pool[obj]
            return t["close"]
        elif obj in self.predata.keys():
            return self.get_data_price(obj,self.predata)
        else:
            return None
    def get_settle_price_byday(self,obj,date=None):
        settle_price = None
        if obj in self.bar_k1d.keys():
            d = datetime.datetime(date.year, date.month, date.day)
            if d in self.bar_k1d[obj].keys():
                t=self.bar_k1d[obj][d]
                if "settle" in t.keys():
                    settle_price = t["settle"]
                elif "SettlementPrice" in t.keys():
                    settle_price = t["SettlementPrice"]
                elif "close" in t.keys():
                    settle_price = t["close"]
                elif "LastPrice" in t.keys():
                    settle_price = t["LastPrice"]
        if settle_price is None:
            if obj in self.bar_pool.keys():
                t = self.bar_pool[obj]
                if "settle" in t.keys():
                    settle_price = t["settle"]
            if settle_price is None:
                if obj in self.price_pool.keys():
                    t = self.bar_pool[obj]
                    if "SettlementPrice" in t.keys():
                        settle_price = t["SettlementPrice"]
                    else:
                        settle_price=t["LastPrice"]
        return settle_price

    def get_data_tradeprice(self,obj,data,trademode="close"):
        if obj in data.keys():
            t = data[obj]
            if trademode in t.keys():
                price = t[trademode]
            elif "LastPrice" in t.keys():
                price = t["LastPrice"]
            else:
                price=t["close"]
            return price
        else:
            return None
    def get_data_price(self,obj,data):
        if obj in data.keys():
            t = data[obj]
            if "LastPrice" in t.keys():
                price = t["LastPrice"]
            else:
                price=t["close"]
            return price
        else:
            return None
    def get_lastsettle_price_byday(self,obj,date=None):
        if obj in self.presettle_byday.keys():
            k=list(self.presettle_byday[obj].keys())
            k.sort()
            if date:
                d=datetime.datetime(date.year,date.month,date.day)
                for i in reversed(k):
                    if i <=d:
                        key=i
                        break
            else:
                key=k[-1]
            presettle_price = self.presettle_byday[obj][key]
            return presettle_price
        else:
            return None
    def get_presettle_price_byday(self,obj,date=None):
        if obj in self.presettle_byday.keys():
            k=list(self.presettle_byday[obj].keys())
            k.sort()
            if date:
                d=datetime.datetime(date.year,date.month,date.day)
                key=None
                for i in reversed(k):
                    if i <d:
                        key=i
                        break
                if key is None:
                    return None
            else:
                key=k[-1]
            presettle_price = self.presettle_byday[obj][key]
            return presettle_price
        else:
            return None
    # def save_presettle_byday(self,data):
    #     for obj,t in data.items():
    #         settle_price = None
    #         if "settle" in t.keys():
    #             settle_price = t["settle"]
    #         elif "SettlementPrice" in t.keys():
    #             settle_price = t["SettlementPrice"]
    #         elif "close" in t.keys():
    #             settle_price = t["close"]
    #         elif "LastPrice" in t.keys():
    #             settle_price = t["LastPrice"]
    #         dt=t["timekey"]
    #         d=datetime.datetime(dt.year, dt.month,dt.day)
    #         if obj not in self.presettle_byday.keys():
    #             self.presettle_byday[obj]={}
    #         self.presettle_byday[obj][d]=settle_price
    def ontimekey(self,timekey):
        if self.timekey:
            if timekey>self.timekey:
                if self.isclosetime:
                    if timekey.hour>=9 and timekey.hour<15:
                        self.isclosetime=False
                    elif timekey.hour>=21 and timekey.hour<=22:
                        self.isclosetime=False
        self.timekey=timekey
    def ontick(self,t):
        self.ontimekey(t["timekey"])
        if "obj" in t.keys():
            obj=t["obj"]
            self.price_pool[obj]=t
        else:
            self.price_pool = t
        for i in self.close_monitor:
            i.ontick(t,self)
    def onbar(self,b):
        self.ontimekey(b["timekey"])
        if "obj" in b.keys():
            obj=b["obj"]
            self.bar_pool[obj]=b
        else:
            self.bar_pool = b
        for i in self.close_monitor:
            i.onbar(b,self)
    def onk1d_bar(self,b):
        obj=b["obj"]
        date=b["timekey"]
        if obj not in self.bar_k1d.keys():
            self.bar_k1d[obj]={}
        self.bar_k1d[obj][date]=b

    def set_close_monitor(self,m):
        self.close_monitor.append(m)
    def add_other_data(self, name, key, v):
        if name not in self.other.keys():
            self.other[name] = {}
        self.other[name][key] = v
    def set_otherdata_graph(self, names):
        if isinstance(names, list):
            for i in names:
                self.otherdata_graph[names] = {"axis":0,"is_selected":False}
        elif isinstance(names, dict):
            for k,v in names.items():
                if isinstance(v,list):
                    self.otherdata_graph[k] = {"axis": v[0], "is_selected": v[1]}
                elif isinstance(v,int):
                    self.otherdata_graph[k] = {"axis":v,"is_selected":False}
                else:
                    self.otherdata_graph[k]=v
    def set_graph(self,name,data,ismaingrap=True):
        if ismaingrap:
            self.set_otherdata_graph({name:0})
        else:
            self.set_otherdata_graph({name:1})
        self.other[name]=data
    def set_otherpos_pldata(self,r):
        self.otherpos_pldata.update(r)

    # ----------------------------------行情等其他数据类结束------------------------------------------------
    # ----------------------------------工作机制类开始------------------------------------------------
    def ondaystart(self):
        #研究用于标记状态
        #实盘时用于准备策略数据
        print("pos_frame没有定义:ondaystart")
        return None
    def ondayend(self, date, data):
        # 研究用于触发每天结算
        # 实盘时用于存数据修改状态
        """:param
        data:{obj:bar/tick}
        必须支持以上业务解析：支持多品种的回测与结算；单品种是多品种的一个特例
        """
        print("pos_frame没有定义:ondayend")
        return None
    def ondayend_bytick(self, date, data):
        # 研究用于触发每天结算
        # 实盘时用于存数据修改状态
        print("pos_frame没有定义:ondayend_bytick")
        return None
    def save(self, url,isProduct=True,product_info={}):
        save(self, url)
        self.getnet_graph(url,isProduct=isProduct,product_info=product_info)

    # ----------------------------------工作机制类结束------------------------------------------------
    # ----------------------------------投资绩效类开始------------------------------------------------
    def set_benck_mark(self, data):

        for k, v in data.items():
            if isinstance(v, list):
                if len(v) == 2:
                    self.benck_mark[k] = {"obj": v[0], "is_selected": v[1], "aixs": 1}
                else:
                    self.benck_mark[k] = {"obj": v[0], "is_selected": v[1], "aixs": v[2]}
            elif isinstance(v, str):
                self.benck_mark[k] = {"obj": v, "is_selected": False, "aixs": 1}
            else:
                self.benck_mark[k] = v

    def get_benck_net(self):
        """:cvar
        标准定义返回基准组的值，dict:{key-基金名称，values值
        """
        t = list(self.fund_his.keys())
        t.sort()
        rst={}
        for name,v in self.benck_mark.items():
            obj=v["obj"]
            rst1 = self.getbenckmark(obj, t)
            if rst1:
                kd = pd.DataFrame(rst1)
                kd["net"] = kd["close"]/rst1[0]["close"]
                kd["net"].fillna(1, inplace=True)
                rst[name]={"data":kd["net"].to_list()}
                rst[name].update(v)
        return rst

    def getbenckmark(self, obj, date_list):
        date_list.sort()
        startdate = date_list[0]
        enddate = date_list[-1]
        if "." not in obj:
            if obj[0]<'3':
                obj=obj+".SH"
            else:
                obj = obj + ".SZ"
        r= xtpredata.deal_data2([obj],startdate,enddate,"none")
        return r[obj]


        # if "." not in obj:
        #     datatool_index0 = self.datatool_index["index"]
        # else:
        #     obj, pcode = obj.split(".")
        #     datatool_index0 = self.datatool_index[pcode]
        # if datatool_index0.isavailable:
        #     rst0 = datatool_index0.get_data(obj, startdate, enddate)
        #     return rst0
        # else:
        #     db = getdb_client(dbname="stock", ip=self.ip)
        #     cu = db["index_k1d"]
        #     rst = {}
        #     predata = None
        #     for i in cu.find(
        #             {"obj": obj, "timekey": {"$gte": startdate, "$lte": enddate}},
        #             {"close": 1, "timekey": 1}).sort([("timekey", 1)]):
        #         # for i in cu.find({"obj":obj,"timekey":{"$gte":startdate.strftime("%Y-%m-%d"),"$lte":enddate.strftime("%Y-%m-%d")}},{"close":1,"timekey":1}).sort([("timekey",1)]):
        #         del i["_id"]
        #         d = i["timekey"]
        #         if predata   is None:
        #             predata = i
        #         rst[d] = i
        #     db.client.close()
        #     rst0 = []
        #     for i in date_list:
        #         if i not in rst.keys():
        #             data = deepcopy(predata)
        #             data["timekey"] = i
        #             rst0.append(data)
        #         else:
        #             data = rst[i]
        #             rst0.append(predata)
        #             predata = data
        #     return rst0
    def orders_his2bs_mark_edot(self,timekey_strn=10,buyinfo={},sellinfo={}):
        rst={}
        for o in self.orders_his:
            obj=o["obj"]
            if obj not in rst.keys():
                rst[obj]={}
            t=rst[obj]
            k=str(o["opentimekey"])[:timekey_strn]
            msg=o["buymsg"]
            name="买"
            for k1,v1 in buyinfo.items():
                if k1 in msg:
                    name=v1
                    break
            if name not in t.keys():
                t[name]={"x":[],"y":[]}
            if k not in t[name]["x"]:
                t[name]["x"].append(k)
                t[name]["y"].append(o["buyprice"])
            k=str(o["closetimekey"])[:timekey_strn]
            # if k not in sellt:
            msg = o["sellmsg"]
            name = "卖"
            for k1, v1 in sellinfo.items():
                if k1 in msg:
                    name = v1
                    break
            if name not in t.keys():
                t[name]={"x":[],"y":[]}
            t[name]["x"].append(k)
            t[name]["y"].append(o["sellprice"])
        return rst
    def calc_bi_pl1(self,isdetail=False,mode=0):
        r={}
        objs=[]
        if self.orders_his:
            if mode == 1:
                orders_his0=[]
                orders_his1 = {}
                for i in self.orders_his:
                    obj=i["obj"]
                    if obj not in objs:
                        objs.append(obj)
                    tk=i["opentimekey"]
                    if tk  not in orders_his1.keys():
                        orders_his1[tk]={}
                    if obj not in orders_his1[tk].keys():
                        orders_his1[tk][obj]=[i]
                    else:
                        orders_his1[tk][obj].append(i)
                for v in orders_his1.values():
                    for vv in v.values():
                        if len(vv)==1:
                            i=vv[0]
                            # i["pl1"]=i["pl"]
                            deltat = i["closetimekey"] - i["opentimekey"]
                            i["holddays"] = deltat.days
                            orders_his0.append(i)
                        else:
                            t=deepcopy(vv[0])
                            tt=pd.DataFrame(vv)
                            t["qty"]=tt["qty"].sum()
                            t["pl"]=tt["pl"].sum()
                            t["buyamount"]=(tt["buyprice"]*tt["qty"]).sum()
                            t["sellamount"] = (tt["sellprice"] * tt["qty"]).sum()
                            # t["pl1"]=t["sellamount"]-t["buyamount"]
                            t["plr"] = t["pl"] / t["buyamount"]
                            t["closetimekey"] = tt["closetimekey"].max()
                            deltat = t["closetimekey"] - t["opentimekey"]
                            t["holddays"] = deltat.days
                            orders_his0.append(t)
                r["调整交易笔"]="是"
            else:
                r["调整交易笔"] = "否"
                for i in self.orders_his:
                    obj=i["obj"]
                    if obj not in objs:
                        objs.append(obj)
                    deltat=i["closetimekey"]-i["opentimekey"]
                    i["holddays"]=deltat.days
                orders_his0 = self.orders_his
            # t1=pd.DataFrame(orders_his0)
            # t2=pd.DataFrame(self.orders_his)
            # pl1=t1["pl"].sum()
            # pl3 = t1["pl1"].sum()
            # pl2 = t2["pl"].sum()

            objs0 = []
            pl0=0
            buyamount0=0
            for obj, v in self.pos.items():
                for bs, vv in v.items():
                    if isinstance(vv, list):
                        for j in vv:
                            if j["qty"] > 0:
                                if obj not in objs0:
                                    objs0.append(obj)
                                if obj not in objs:
                                    objs.append(obj)
                                i = j["detail"][0]
                                p = self.bar_pool[obj]["close"]
                                if bs == "buy":
                                    pl0 = pl0+i["qty"] * (p * (1 - self.fee) - i["buyprice"])
                                else:
                                    pl0 = pl0+i["qty"] * (i["sellprice"] - p * (1 + self.fee))
                    else:
                        if vv["qty"] > 0:
                            if obj not in objs0:
                                objs0.append(obj)
                            if obj not in objs:
                                objs.append(obj)
                            for i in vv["detail"]:
                                p = self.bar_pool[obj]["close"]
                                if bs == "buy":
                                    pl0 = pl0+i["qty"] * (p * (1 - self.fee) - i["buyprice"])
                                else:
                                    pl0 = pl0+i["qty"] * (i["sellprice"] - p * (1 + self.fee))

            ordersd = pd.DataFrame(orders_his0)
            ordersd.sort_values(["plr"],inplace=True)
            r["总盈亏"] = ordersd["pl"].sum()+pl0
            r["已实现总盈亏"] = ordersd["pl"].sum()
            r["持仓浮动盈亏"] = pl0
            # ordersd["plr0"]=ordersd
            if self.cashin_total>0:
                cashin_total=self.cashin_total
            else:
                cashin_total=0
            r["累计盈亏率"] = r["总盈亏"] / (self.cash0+cashin_total)
            r["已实现盈亏率"] = r["已实现总盈亏"] / (self.cash0 + cashin_total)
            r["浮动盈亏率"] = r["持仓浮动盈亏"] / (self.cash0 + cashin_total)
            r["交易股票"] = len(objs)
            r["未平仓股票"]=len(objs0)
            r["换手率"] = ordersd["sellamount"].sum() / (self.cash0+cashin_total)
            r["交易时间"] = [self.orders_his[0]["opentimekey"], self.orders_his[-1]["closetimekey"]]
            r["交易笔数"] = len(self.orders_his)
            r["手数"] = int(ordersd["qty"].sum())
            r["手续费总额"] = ordersd["fee"].sum()
            ordersd["tick"] = ordersd["sellprice"] - ordersd["buyprice"]
            r["点数分布"] = ordersd["tick"].quantile([0, .25, .5, .75, 1]).to_dict()
            r["盈亏分布"] = ordersd["pl"].quantile([0, .25, .5, .75, 1]).to_dict()
            r["总交易额"] = ordersd["buyamount"].sum()+ordersd["sellamount"].sum()
            r["换手率(双向)"] = r["总交易额"] / (self.cash0+cashin_total)

            pl1 = ordersd[ordersd["pl"] > 0]
            pl0 = ordersd[ordersd["pl"] < 0]
            r["胜率"] = len(pl1) / len(self.orders_his)
            r["累计收益比累计投入"]=ordersd["pl"].sum()/ordersd["buyamount"].sum()
            r["平均每笔收益率"]=ordersd["plr"].mean()
            r["收益率标准差"]=ordersd["plr"].std()
            r["每笔收益率一倍标准差区间"]=[ordersd["plr"].mean()-r["收益率标准差"],ordersd["plr"].mean()+r["收益率标准差"]]
            if len(pl0) != 0 and pl0["pl"].sum()!=0 and len(pl1) !=0:
                r["盈亏比"] = (pl1["pl"].sum() / len(pl1)) / (abs(pl0["pl"].sum()) / len(pl0))
                r["亏损"] = {"笔数":len(pl0), "盈亏":pl0["pl"].sum(), "平均每笔赚":pl0["pl"].sum() / len(pl0)}
            else:
                r["盈亏比"] = 0
                r["亏损"] = []
            r["期望收益"]=r["胜率"]*r["盈亏比"]+r["胜率"]-1
            if len(pl1) != 0:
                r["盈利"] = {"笔数":len(pl1), "盈亏":pl1["pl"].sum(), "平均每笔亏":pl1["pl"].sum() / len(pl1)}
            else:
                r["盈利"] = []
            if isdetail:
                order1={
                    "总盈亏":pl1["pl"].sum(),
                    "累计盈亏率":pl1["pl"].sum()/(self.cash0+cashin_total),
                    "交易笔数":len(pl1),
                    "盈亏分布":pl1["pl"].quantile([0, .25, .5, .75, 1]).to_dict(),
                    "盈亏(%)分布": pl1["plr"].quantile([0, .25, .5, .75, 1]).to_dict(),
                    "持有天数分布":pl1["holddays"].quantile([0, .25, .5, .75, 1]).to_dict(),
                    "最大盈利":pl1["pl"].max(),
                    "最小盈利":pl1["pl"].min(),
                    "最大盈利(%)": pl1["plr"].max(),
                    "最小盈利(%)": pl1["plr"].min(),
                    "最大持有天": pl1["holddays"].max(),
                    "最小持有天": pl1["holddays"].min(),
                }
                order0={
                    "总盈亏": pl0["pl"].sum(),
                    "累计盈亏率": pl0["pl"].sum() / (self.cash0 + cashin_total),
                    "交易笔数": len(pl0),
                    "盈亏分布": pl0["pl"].quantile([0, .25, .5, .75, 1]).to_dict(),
                    "盈亏(%)分布": pl0["plr"].quantile([0, .25, .5, .75, 1]).to_dict(),
                    "持有天数分布": pl0["holddays"].quantile([0, .25, .5, .75, 1]).to_dict(),
                    "最大盈利": pl0["pl"].max(),
                    "最小盈利": pl0["pl"].min(),
                    "最大盈利(%)": pl0["plr"].max(),
                    "最小盈利(%)": pl0["plr"].min(),
                    "最大持有天": pl0["holddays"].max(),
                    "最小持有天": pl0["holddays"].min(),
                }
                r["盈利单情况"] = order1
                r["亏损单情况"] = order0
                posd=[]
                objs0=[]
                for obj,v in self.pos.items():
                    for bs,vv in v.items():
                        if isinstance(vv,list):
                            for j in vv:
                                if j["qty"]>0:
                                    if obj not in objs0:
                                        objs0.append(obj)
                                    i= j["detail"][0]
                                    p=self.bar_pool[obj]["close"]
                                    if bs=="buy":
                                        i["pl"] =i["qty"]*(p*(1-self.fee)-i["buyprice"])
                                        i["plr"] = i["pl"] / i["buyamount"]
                                    else:
                                        i["pl"] =i["qty"]*(i["sellprice"]-p*(1+self.fee))
                                        i["plr"] =i["pl"]/i["sellamount"]
                                    deltat=self.timekey-i["opentimekey"]
                                    i["holddays"] =deltat.days
                                    posd.append(i)
                        else:
                            if vv["qty"]>0:
                                if obj not in objs0:
                                    objs0.append(obj)
                                for i in vv["detail"]:
                                    p = self.bar_pool[obj]["close"]
                                    if bs == "buy":
                                        i["pl"] = i["qty"] * (p * (1 - self.fee) - i["buyprice"])
                                        i["plr"] = i["pl"] / i["buyamount"]
                                    else:
                                        i["pl"] = i["qty"] * (i["sellprice"] - p * (1 + self.fee))
                                        i["plr"] = i["pl"] / i["sellamount"]
                                    deltat = self.timekey - i["opentimekey"]
                                    i["holddays"] = deltat.days
                                    posd.append(i)
                if posd:
                    posdd=pd.DataFrame(posd)
                    posdd0=posdd[posdd["pl"] < 0]
                    posdd1=posdd[posdd["pl"] > 0]
                    pos1={
                        "未平仓股票数":len(objs0),
                        "总笔数":len(posdd),
                        "浮动盈亏":posdd["pl"].sum(),
                        "浮动盈亏率":posdd["pl"].sum()/(self.cash0+cashin_total),
                        "盈利笔数":len(posdd1),
                        "亏损笔数":len(posdd0),
                        "盈亏分布": posdd["pl"].quantile([0, .25, .5, .75, 1]).to_dict(),
                        "盈亏(%)分布": posdd["plr"].quantile([0, .25, .5, .75, 1]).to_dict(),
                        "持有天数分布": posdd["holddays"].quantile([0, .25, .5, .75, 1]).to_dict(),
                        "最大盈利": posdd["pl"].max(),
                        "最小盈利": posdd["pl"].min(),
                        "最大盈利(%)": posdd["plr"].max(),
                        "最小盈利(%)": posdd["plr"].min(),
                        "最大持有天": posdd["holddays"].max(),
                        "最小持有天": posdd["holddays"].min(),
                    }
                    pos1["胜率"] = len(posdd1) / len(posdd)
                    if len(posdd0) != 0 and posdd0["pl"].sum()!=0 and len(posdd1)!=0:#{"笔数":len(pl1), "盈亏":pl1["pl"].sum(), "平均每笔亏":pl1["pl"].sum() / len(pl1)}
                        pos1["盈亏比"] = (posdd1["pl"].sum() / len(posdd1)) / (abs(posdd0["pl"].sum()) / len(posdd0))
                        pos1["亏损"] = {"笔数":len(posdd0), "盈亏":posdd0["pl"].sum(), "平均每笔亏":posdd0["pl"].sum() / len(posdd0)}
                    else:
                        pos1["盈亏比"] = 0
                        pos1["亏损"] = {}
                    if len(posdd1) != 0:
                        pos1["盈利"] = {"笔数":len(posdd1), "盈亏":posdd1["pl"].sum(), "平均每笔亏":posdd1["pl"].sum() / len(posdd1)}
                    else:
                        pos1["盈利"] = {}
                    r["持仓单情况"] = pos1
                else:
                    pos1 = {
                        "未平仓股票数": 0,
                        "总笔数": 0,
                        "浮动盈亏": 0,
                        "浮动盈亏率": 0,
                        "盈利笔数": 0,
                        "亏损笔数": 0,
                        "盈亏分布": [],
                        "盈亏(%)分布": [],
                        "持有天数分布": [],
                        "最大盈利": None,
                        "最小盈利": None,
                        "最大盈利(%)": None,
                        "最小盈利(%)": None,
                        "最大持有天": None,
                        "最小持有天": None,
                    }
                    pos1["胜率"] = None
                    pos1["盈亏比"] = 0
                    pos1["亏损"] = {}
                    pos1["盈利"] = {}
        else:
            r["总盈亏"] = 0
            r["累计盈亏率"] = 0
            r["交易股票"] = 0
            r["换手率"] = 0
            r["交易时间"] = []
            r["交易笔数"] = 0
            r["手数"] = 0
            r["手续费总额"] = 0
            r["点数分布"] = {}
            r["盈亏分布"] = {}
            r["总交易额"] = 0
            r["换手率"] = 0
            r["胜率"] = 0
            r["盈亏比"] = 0
            r["累计收益比累计投入"]=0
            r["平均每笔收益率"]=0
            r["收益率标准差"]=0
            r["每笔收益率一倍标准差区间"]=0
            r["期望收益"]=0
            r["亏损"] = 0
            r["盈利"] = 0
            if isdetail:
                r["盈利单情况"]={}
                r["亏损单情况"]={}
                r["持仓单情况"]={}
        return r
    def calc_net_pl2(self,isdetail=False,tradedays=None):
        r={}
        if self.fund_his:
            if not self.return_his:
                f = pd.Series(self.fund_his)
                f.sort_index(inplace=True)
                f1 = f.pct_change()
                self.return_his=f1.to_dict()
            r,detailinfo = performance_net(self.return_his, start_date=None, end_date=None, isdetail=0, pos_rate=self.posrate_his,tradedays=tradedays)
            if isdetail:
                r["detailinfo"]=detailinfo
        return r
    def calc_pl3_benck(self,isdetail=False):#对比基准下的绩效
        pass
    def calc_pl4_byorder(self,args):#按订单开仓归因，平仓，股票类型归因等
        """
        结果：金额归因（交易机会），盈亏归因
        openmsg,closemsg,buymsg,sellmsg,obj
        """
        rst={}
        a0=0
        pl0=0
        for k,v in args.items():
            rst[k]={}
            for o in self.orders_his:
                if "closeamount" in o.keys():
                    a0=a0+o["closeamount"]
                else:
                    a0 = a0 + o["sellamount"]
                pl0=pl0+o["pl"]
                for key in v:
                    if key not in rst[k].keys():
                        rst[k][key]={"金额":0,"盈亏":0}
                    if key in o[k]:
                        if "closeamount" in o.keys():
                            rst[k][key]["金额"]=rst[k][key]["金额"]+o["closeamount"]
                        else:
                            rst[k][key]["金额"] = rst[k][key]["金额"] + o["sellamount"]
                        rst[k][key]["盈亏"] = rst[k][key]["盈亏"] + o["pl"]
                        break
        for k,v in rst.items():
            for key,vv in v.items():
                vv["金额贡献(%)"]=round(100*vv["金额"]/a0,2)
                vv["盈亏贡献(%)"]=round(100*vv["盈亏"]/pl0,2)
        return rst
    def pl(self,tradedays=None,isdetail=False,mode=0):
        # if self.r:
        #     return self.r
        r = self.calc_bi_pl1(isdetail,mode)
        r.update(self.calc_net_pl2(isdetail,tradedays))
        # if isdetail:
        #     if self.orders_his:
        #         ordersd = pd.DataFrame(self.orders_his)
        if r["累计收益率"]!=np.Inf:
            if not self.havecashin:
                amount=r["累计收益率"]*self.cash0
                if int(r["总盈亏"])!=int(amount):
                    print("怀疑持仓库结算错误，或回测结束是持仓头寸未了结，请检查，两种算法存在差额",r["总盈亏"],amount,self.fund["cash"],self.cash0)
            # else:
            #     if r["总盈亏"]>0 and r["productp_total_r"]<0:
            #         print("怀疑持仓库结算错误，请检查，两种算法存在差额", r["总盈亏"], r["productp_total_r"], self.fund["cash"], self.cash0)
            #     elif r["总盈亏"]<0 and r["productp_total_r"]>0:
            #         print("怀疑持仓库结算错误，请检查，两种算法存在差额", r["总盈亏"], r["productp_total_r"], self.fund["cash"], self.cash0)
        else:
            print("怀疑持仓库结算错误，或回测结束是持仓头寸未了结，请检查，两种算法存在差额", r["总盈亏"], r["累计收益率"],self.fund["cash"],self.cash0)
        self.r = r
        return r
    def get_pldata(self,names=["产品净值","回撤","仓位",]):
        r={}
        k1=names[0]
        k2 = names[1]
        k3 = names[2]
        if self.return_his:
            rr = pf.TSeries(self.return_his)
            rr.sort_index(inplace=True)
            rr0 = rr + 1
            rr0 = rr0.cumprod()
            r[k1]=rr0.to_list()

        else:
            f = pd.Series(self.fund_his)
            f.sort_index(inplace=True)
            f2 = f / self.cash0
            r[k1] = f2.to_list()
            f1 = f.pct_change()
            rr = pf.TSeries(f1)
        rr.freq = "D"
        r[k2] = rr.drawdown_idx().abs().to_list()
        r[k3] = pd.Series(self.posrate_his).to_list()

        return r
    def draw_notebook(self,isProduct=True):
        c=self.draw_echarts(isProduct=isProduct)
        c.render_notebook()

    def draw_echarts(self,isProduct=True,product_info={},name="net"):
        if isProduct:
            return self.draw_echarts_0(product_info=product_info,name=name)
        else:
            return self.draw_echarts_1(name=name)
    def draw_echarts_1(self,name="net"):
        import pyecharts.options as opts
        from pyecharts.charts import Line, Grid
        rst = pd.Series(self.fund) / self.cash0
        rst = pd.DataFrame(rst, columns=["fund"])
        rst["timekey"] = rst.index
        rst["x"] = rst["timekey"].apply(lambda i: i.strftime("%Y%m%d"))
        from jili.report.finance_chart import chart
        chart0 = chart(timekey_strn=10)
        # c=chart0.mainchart_net()
        c=Line(init_opts=opts.InitOpts(height="842px", width="1842px"))
        x = rst["x"].to_list()
        c.add_xaxis(x)
        chart0.x = x
        c.set_global_opts(title_opts=opts.TitleOpts(title=name),
                         yaxis_opts=opts.AxisOpts(
                             name="基准",
                             name_location="start",
                             type_="value",
                             min_='dataMin',
                             max_='dataMax',
                             is_inverse=False,
                             axistick_opts=opts.AxisTickOpts(is_show=False),
                             splitline_opts=opts.SplitLineOpts(is_show=True),
                         ),
                         # tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
                         # datazoom_opts=[
                         #     opts.DataZoomOpts(type_="inside", range_start=0, range_end=100),
                         # ],
                         # xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False,
                         #                          splitline_opts=opts.SplitLineOpts(is_show=True)),
                         )
        c.extend_axis(
        yaxis=opts.AxisOpts(
            name="指标",
            min_='dataMin',
            max_='dataMax',
            is_inverse=False,
            splitline_opts=opts.SplitLineOpts(is_show=True)))

        benck_nets = self.get_benck_net()
        for name, v in benck_nets.items():
            yy=v["data"]
            yaxis_index=v.get("axis",0)
            is_selected=v.get("is_selected",False)
            c.add_yaxis(series_name=name,
                        y_axis=yy,
                        yaxis_index=yaxis_index,
                        is_selected=is_selected,
                        linestyle_opts=opts.LineStyleOpts(width=1),is_smooth=True,
                        label_opts=opts.LabelOpts(is_show=False),
                        )
        color = 0
        color_set = ['#483D8B','#8470FF','#FF8247','#458B00','#00BFFF',
                     '#4682B4','#B0C4DE','#00CED1','#FF3030','#8B1A1A',
                     '#98FB98','#32CD32','#6B8E23','#FFFF00','#DAA520',
                     '#B8860B']

        aa={}
        for i, v in self.otherdata_graph.items():
            yaxis_index = v.get("axis", 1)
            is_selected = v.get("is_selected", False)
            if i in self.other.keys():
                y0 = list(self.other[i].values())
                if yaxis_index < 2:
                    c.add_yaxis(series_name=i,
                                y_axis=y0,
                                yaxis_index=yaxis_index,
                                is_selected=is_selected,
                                linestyle_opts=opts.LineStyleOpts(width=2.5),
                                areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
                                label_opts=opts.LabelOpts(is_show=False),
                                color = color_set[color]
                                )
                else:
                    yaxis_index1 = yaxis_index - 2
                    t0 = v.get("type", "line")
                    if yaxis_index1 not in aa.keys():
                        t = {"type": t0, "data": [y0], "opts": [{"name": i, "yaxis_index": yaxis_index}]}
                        aa[yaxis_index1] = t
                    else:
                        aa[yaxis_index1]["data"].append(y0)
                        aa[yaxis_index1]["opts"].append({"name": i, "yaxis_index": yaxis_index})
            else:
                print("pos.other 不存在数据", i)
            color = color + 1
        chart0.set_mainchart(c)
        chart0.set_name(name)
        for ni in sorted(aa):
            t=aa[ni]
            chart0.add_sub_chart(t["type"], t["data"],x=x,opts_data=t["opts"])
        c = chart0.draw(width="1800px", high="l3")
        return c

    def draw_echarts_0(self,product_info={},name="net"):
        # from pyecharts.globals import CurrentConfig
        # CurrentConfig.ONLINE_HOST = "http://192.168.10.44:8000/assets/"
        import pyecharts.options as opts
        from pyecharts.charts import Line, Grid
        f = pd.Series(self.fund_his)
        f.sort_index(inplace=True)
        rst = pd.DataFrame(f)
        rst["timekey"] = rst.index
        rst["x"] = rst["timekey"].apply(lambda i: i.strftime("%Y%m%d"))

        if self.return_his:
            rr = pf.TSeries(self.return_his)
            rr.sort_index(inplace=True)
            rr0 = rr + 1
            rr0 = rr0.cumprod()
            y1 = rr0.to_list()
        else:
            f1 = f.pct_change()
            rr = pf.TSeries(f1)
            f2 = f / self.cash0
            y1 = f2.to_list()
        rr.freq = "D"
        y3 = rr.drawdown_idx().abs().to_list()
        y2 = pd.Series(self.posrate_his).to_list()
        from jili.report.finance_chart import chart
        chart0 = chart(timekey_strn=10)
        # c = chart0.mainchart_net()
        c = Line(init_opts=opts.InitOpts(height="842px", width="1842px"))
        x=rst["x"].to_list()
        c.add_xaxis(x)
        chart0.x=x
        c.extend_axis(
            yaxis=opts.AxisOpts(
                name="净值",
                min_='dataMin',
                max_='dataMax',
                splitline_opts=opts.SplitLineOpts(is_show=True)
            )
        )
        c.set_global_opts(title_opts=opts.TitleOpts(title=name),
             yaxis_opts=opts.AxisOpts(
                 name="仓位",
                 name_location="start",
                 type_="value",
                 max_=3,
                 is_inverse=True,
                 axistick_opts=opts.AxisTickOpts(is_show=False),
                 splitline_opts=opts.SplitLineOpts(is_show=True),
             ),
             # tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
             # datazoom_opts=[
             #     opts.DataZoomOpts(range_start=0, range_end=100),
             #     opts.DataZoomOpts(type_="inside", range_start=0, range_end=100),
             # ],
             # xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False,
             #                          splitline_opts=opts.SplitLineOpts(is_show=True)),
             )

        c.add_yaxis("产品", y1, yaxis_index=1,linestyle_opts=opts.LineStyleOpts(width=2.5),#is_selected=product_info.get("产品",True),
                   label_opts=opts.LabelOpts(is_show=False), )
        c.add_yaxis(
            series_name="仓位",
            y_axis=y2,
            yaxis_index=0,
            # is_selected=product_info.get("仓位", True),
            linestyle_opts=opts.LineStyleOpts(),
            areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
            label_opts=opts.LabelOpts(is_show=False),
            )
        c.add_yaxis(
            series_name="回撤",
            y_axis=y3,
            yaxis_index=0,
            # is_selected=product_info.get("回撤", True),
            linestyle_opts=opts.LineStyleOpts(),
            areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
            label_opts=opts.LabelOpts(is_show=False),
        )



        for name0,yy in self.otherpos_pldata.items():
            if "净值" in name0:
                yaxis_index0=1
            else:
                yaxis_index0 = 0
            c.add_yaxis(series_name=name0,
                        y_axis=yy,
                        yaxis_index=yaxis_index0,
                        linestyle_opts=opts.LineStyleOpts(width=1),
                        label_opts=opts.LabelOpts(is_show=False),
                        )
        benck_nets=self.get_benck_net()
        for name0, v in benck_nets.items():
            yy=v["data"]
            yaxis_index=v.get("axis",1)
            # is_selected=v.get("is_selected",True)
            c.add_yaxis(series_name=name0,
                        y_axis=yy,
                        yaxis_index=yaxis_index,
                        # is_selected=is_selected,
                        linestyle_opts=opts.LineStyleOpts(width=1),
                        label_opts=opts.LabelOpts(is_show=False),
                        )
        aa={}
        for i, v in self.otherdata_graph.items():
            yaxis_index = v.get("axis", 1)
            # is_selected = v.get("is_selected", False)
            if i in self.other.keys():
                y0 = list(self.other[i].values())
                if len(self.fund_his)-len(y0)==1:
                    y0.insert(0,y0[0])
                if yaxis_index<2:
                    c.add_yaxis(series_name=i,
                                y_axis=y0,
                                yaxis_index=yaxis_index,
                                # is_selected=is_selected,
                                linestyle_opts=opts.LineStyleOpts(),
                                areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
                                label_opts=opts.LabelOpts(is_show=False),
                                )
                else:
                    yaxis_index1=yaxis_index-2
                    t0=v.get("type","line")
                    if yaxis_index1 not in aa.keys():
                        t = {"type": t0, "data": [y0], "opts": [{"name": i, "yaxis_index": yaxis_index}]}
                        aa[yaxis_index1]=t
                    else:
                        aa[yaxis_index1]["data"].append(y0)
                        aa[yaxis_index1]["opts"].append({"name": i, "yaxis_index": yaxis_index})
            else:
                print("pos.other 不存在数据", i)
        chart0.set_mainchart(c)
        chart0.set_name(name)
        for ni in sorted(aa):
            t=aa[ni]
            chart0.add_sub_chart(t["type"], t["data"],x=x,opts_data=t["opts"])
        c=chart0.draw(width="1800px",high="l3")
        return c
    def draw_html(self, url=None,isProduct=True,product_info={},name="net",ispng=False):
        c=self.draw_echarts(isProduct=isProduct,product_info=product_info,name=name)
        if url:
            if url.split(".")[-1]!="html":
                htmlfigurl = url + ".html"
            else:
                htmlfigurl=url
            baseurl=os.path.dirname(htmlfigurl)
            if  not os.path.exists(baseurl):
                os.mkdir(baseurl)
            c.render(htmlfigurl)
            if ispng:
                try:
                    from pyecharts.render import make_snapshot
                    # 使用snapshot-selenium 渲染图片
                    from snapshot_selenium import snapshot as snapshot_chrome
                    outfigurl=htmlfigurl.replace(".html",".png")
                    make_snapshot(snapshot_chrome, htmlfigurl, outfigurl, is_remove_html=False, delay=1, pixel_ratio=1)
                except Exception as e:
                    print(e)
        return c
    def load(self,url,nodeal=[],update={},onlydeal=[]):
        sspos=load(url)
        if onlydeal:
            for k, v in sspos.__dict__.items():
                if k in onlydeal:
                    self.__dict__[k] = v
        else:
            for k,v in sspos.__dict__.items():
                if k not in nodeal:
                    self.__dict__[k]=v
            for k,v in update.items():
                self.__dict__[k] = v
    def getnet_graph(self, url=None,isProduct=True,product_info={}):
        rr = pd.Series(self.return_his)
        rr.sort_index(inplace=True)
        rr=rr+1
        rr=rr.cumprod()
        plt.plot(rr)
        if url:
            plt.savefig(url + ".jpg")
            self.draw_html(url,isProduct=isProduct,product_info=product_info)
        if not self.is_graphs:
            plt.close()
    def getnet_fig(self, url):
        rr = pd.Series(self.return_his)
        rr.sort_index(inplace=True)
        rr = rr + 1
        rr = rr.cumprod()
        plt.plot(rr)
        plt.savefig(url + ".jpg")
        if not self.is_graphs:
            plt.close()
    def getposrate_graph(self):
        return pd.Series(self.posrates).plot()
    def repare_product_data(self,sspos):
        rr = pf.TSeries(sspos.return_his)
        rr.sort_index(inplace=True)
        rr0 = rr + 1
        rr0 = rr0.cumprod()
        y1 = rr0.to_dict()
        y3 = rr.drawdown_idx().abs().to_dict()
        return y1,y3,sspos.posrate_his

    def save_orders_xlsx(self,url,products={},names=[],ssposs=[],sspos_urls=[]):

        from jili.tool import deepdict2dict
        from jili.tool.tofile import df_to_excel
        products0={"产品":self}
        for name,pos in products.items():
            products0[name] = load(pos)
        for i in sspos_urls:
            # burl=os.path.dirname(i)
            name=os.path.basename(i)
            name=name.replace(".pkl","")
            products0[name]=load(i)
        n=0
        for pos in ssposs:
            name=names[n]
            products0[name] =pos
        rr = []
        for name,pos in products0.items():
            r=pos.pl(True)
            r["产品"]=name
            rr.append(deepdict2dict(r))
        import pandas as pd
        rd = pd.DataFrame(rr)
        rd = rd.T
        data = {"绩效详情": rd}
        for name, pos in products0.items():
            data[name]=pos.orders_his
        df_to_excel(data, url)
    def compare_product(self,url,compare_type="posrate",maxposrate=None,r=0.5,products={},names=[],ssposs=[],sspos_urls=[]):
        from jili.core import load
        from jili.tool import deepdict2dict
        from jili.tool.tofile import df_to_excel
        products0={"产品":self}
        for name,pos in products.items():
            products0[name] = load(pos)
        for i in sspos_urls:
            # burl=os.path.dirname(i)
            name=os.path.basename(i)
            name=name.replace(".pkl","")
            products0[name]=load(i)
        n=0
        for pos in ssposs:
            name=names[n]
            products0[name] =pos
        for name,pos in products0.items():
            if name!="产品":
                self.add_other_product(name, pos, compare_type=compare_type, maxposrate=maxposrate)
        rr = []
        for name, pos in products0.items():
            r = pos.pl(True)
            r["产品"] = name
            rr.append(deepdict2dict(r))
        import pandas as pd
        rd = pd.DataFrame(rr)
        rd = rd.T
        data = {"绩效详情": rd}
        df_to_excel(data, url)
        self.draw_html(url=url+".html", name="对比")
    def add_other_product(self,name,sspos,compare_type="posrate",maxposrate=None):
        """

        Args:
            sspos:
            要求具有同长度的产品
            compare_type:拉齐对比场景：None无，posrate同一仓位暴露
            maxposrate:是否拉齐标准仓位，不设置就用本产品的最大仓位
        Returns:
        无返回值，画图会画产品净值,仓位，回撤三个数据点；全部加在otherdata中
        """
        if compare_type=="posrate":
            if maxposrate is None:
                maxposrate=max(list(self.posrate_his.values()))
            else:
                maxposrate0 = max(list(self.posrate_his.values()))
                if round(maxposrate0,3)!=round(maxposrate,3):
                    f=maxposrate/maxposrate0
                    posrates={}
                    for d,v in self.posrate_his.items():
                        posrates[d]=v*f
                    self.posrate_his=deepcopy(posrates)
                    return_his0={}
                    for d,v in self.return_his.items():
                        return_his0[d]=v*f
                    self.return_his=deepcopy(return_his0)
        maxposrate0 = max(list(sspos.posrate_his.values()))
        if round(maxposrate0, 3) != round(maxposrate, 3):
            f = maxposrate / maxposrate0
            posrates = {}
            for d, v in sspos.posrate_his.items():
                posrates[d] = v * f
            sspos.posrate_his = deepcopy(posrates)
            return_his0 = {}
            for d, v in sspos.return_his.items():
                return_his0[d] = v * f
            sspos.return_his = deepcopy(return_his0)
        key1=name+"产品"
        key2=name+"回撤"
        key3=name+"仓位"
        self.other[key1],self.other[key2],self.other[key3]=self.repare_product_data(sspos)
        self.otherdata_graph[key1] = {"axis": 1, "type": "line"}
        self.otherdata_graph[key2] = {"axis": 0, "type": "line"}
        self.otherdata_graph[key3] = {"axis": 0, "type": "line"}
    # ----------------------------------投资绩效类结束------------------------------------------------
    def create_fund(self,cash):
        msg={}
        msg["prebalance"]=cash  # fix new
        msg["cashin"] =0  # update new
        msg["closepl0"] = 0 # update new
        msg["pl0"] = 0
        msg["fee"] = 0  # update new

        msg["balance"] = cash  # =prebalance+cashin+closepl0+pl0+fee
        msg["margin"] = 0
        msg["frozen"] = 0

        msg["cash"] = cash
        return msg
    def create_order(self):
        """:param
        1.价格是含税费净价格
        2.盈亏是净盈亏
        3.fee是包含了冲击成本的

        """
        order = {"obj": None, "bs":None,"qty": 0, "fee":0,"pl":0,
                 "opentimekey": None,"buyprice": 0, "buyamount": 0, "buymsg": "",
                 "closetimekey":None,"sellprice": 0, "sellamount": 0, "sellmsg": ""}
        return order
    def create_pos(self):
        pos = {"obj": None,"bs":None, "costprice": 0, "costamount": 0, "qty":0,
             "close_pl": 0, "closevalue": 0, "openvalue": 0,"highprice":0,"fee":0,
             "detail": [],"detail":[]}
        return pos